/*
//Messages
native msg(playerid, colour text[])
native msga(colour, text[])
native msgF(playerid, color, message[], stuff...)
native msgaF(color, message[], stuff...)
native _
//Player
native PlaySoundForAll(sound)for(new i;i<PLAYERS;i++)PlayerPlaySound(i, sound, 0, 0, 0);
native SendClientMessageToAllEx(playerid, color, message[])for(new a=0;a<PLAYERS;a++)if(a!=playerid) SendClientMessage(a, color, message);
native GetName(playerid)
native GivePlayerHealth(playerid, Float:health)
native GivePlayerArmour(playerid, Float:armour)
native GivePlayerPoints(playerid, Score)
native IsPlayerInArea(playerid, Float:min_x, Float:min_y, Float:max_x, Float:max_y)
native IsPlayerInCube(playerid, xmin, ymin, zmin, xmax, ymax, zmax)
native GetXYInFrontOfPlayer(playerid, &Float:x, &Float:y, Float:distance)
native IsValidSkin(skinid)
native IsPlayerSpawned(playerid)
native PlayerNameIs(playerid, const name[]);
native PlayerNameContains(playerid, const name[]);
native PlayerNameStartsWith(playerid, const name[]);
native PlayerNameEndsWith(playerid, const name[]);
native ReversePlayerName(playerid);
native _
//Server
native strtok(const string[], &index)
native strrest(const string[], &index)
native strreplace(trg[],newstr[],src[])
native ret_memcpy(source[],index=0,numbytes)
native strcpy(dest[], source[], max, len = -1)
native token_by_delim(const string[], return_str[], delim, start_index)
native IsKeyJustDown(key, newkeys, oldkeys)
native UnderscoreToSpace(name[])
native GetSkinGender(skinID)
native GetDist3D(Float:x, Float:y, Float:z, Float:x2, Float:y2, Float:z2)
native GetDist2D(Float:x, Float:y, Float:x2, Float:y2)
native GetPlayerDist3D(player1, player2)
native GetPlayerDist2D(player1, player2)
native IsPointInPolygon(point_x, point_y, Float:x, Float:y...)
native IsDateReached(day,month,year)
native IsNumeric(const string[])
native _
//Vehicle
native GetPlayersInVehicle(vehicleid)
native SetVehicleModel(playerid, vehicleid, modelid)
native IsPlayerInInvalidNosVehicle(playerid,playerveh)
native IsPlayerInCar(playerid)
native SpawnCarForPlayer(playerid, vehid)
native LoadStaticVehiclesFromFile(const filename[])
native _
//Zones
native GetPlayer2DZone(playerid, zone[])
native GetPlayer3DZone(playerid, zone[])
native IsPlayerInZone(playerid, zone[])
native _
//Angles
native SetPlayerToFacePlayer(playerid, targetid)
native IsPlayerBehindPlayer(playerid, targetid, Float:dOffset)
native IsPlayerFacingPlayer(playerid, targetid, Float:dOffset)
native AngleInRangeOfAngle(Float:a1, Float:a2, Float:range)
*/



//==============================================================================Geometrical / Mathematical Functions

forward Float:GetDistancePointLine(Float:line_x,Float:line_y,Float:line_z,Float:vector_x,Float:vector_y,Float:vector_z,Float:point_x,Float:point_y,Float:point_z);

stock Float:Distance(Float:x1,Float:y1,Float:z1,Float:x2,Float:y2,Float:z2)
	return floatsqroot((((x1-x2)*(x1-x2))+((y1-y2)*(y1-y2))+((z1-z2)*(z1-z2))));

stock Float:GetDistancePointLine(Float:line_x,Float:line_y,Float:line_z,Float:vector_x,Float:vector_y,Float:vector_z,Float:point_x,Float:point_y,Float:point_z)
	return floatsqroot(floatpower((vector_y) * ((point_z) - (line_z)) - (vector_z) * ((point_y) - (line_y)), 2.0)+floatpower((vector_z) * ((point_x) - (line_x)) - (vector_x) * ((point_z) - (line_z)), 2.0)+floatpower((vector_x) * ((point_y) - (line_y)) - (vector_y) * ((point_x) - (line_x)), 2.0))/floatsqroot((vector_x) * (vector_x) + (vector_y) * (vector_y) + (vector_z) * (vector_z));

stock Float:GetAngleToPoint(Float:fPointX, Float:fPointY, Float:fDestX, Float:fDestY)
	return atan2((fDestY - fPointY), (fDestX - fPointX)) + 270.0;

stock GetXYFromAngle(&Float:x, &Float:y, Float:a, Float:distance)
	x+=(distance*floatsin(-a,degrees)),y+=(distance*floatcos(-a,degrees));

stock Float:CalculateVelocity(Float:X, Float:Y, Float:Z)
	return (floatsqroot((X*X)+(Y*Y)+(Z*Z))*200);

stock Float:frandom(Float:max, Float:min = 0.0, dp = 4)
{
    new
        Float:mul = floatpower(10.0, dp),
        imin = floatround(min * mul),
        imax = floatround(max * mul);
    return float(random(imax - imin) + imin) / mul;
}
stock IsPointInPolygon(Float: point_X, Float: point_Y, { Float, _ }: ...)
{
    #define MAX_POINTS (32)

    new
        args_Total = numargs(),
        polygon_Sides = (args_Total - 2) / 2;
    if((args_Total - 2) & 0b1 || MAX_POINTS <= polygon_Sides || polygon_Sides < 3)
        return 0;

    new
        Float: polygon_Data[2][MAX_POINTS],
        cross_Total;

    #undef MAX_POINTS

    for(new i = 2, j; i < args_Total; i += 2, ++j)
    {
        polygon_Data[0][j] = Float: getarg(i);
        polygon_Data[1][j] = Float: getarg(i + 1);
    }
    for(new i, j = polygon_Sides - 1; i < polygon_Sides; j = i, ++i)
    {
        if(polygon_Data[1][i] < point_Y && polygon_Data[1][j] >= point_Y || polygon_Data[1][j] < point_Y && polygon_Data[1][i] >= point_Y)
        {
            if(polygon_Data[0][i] + (point_Y - polygon_Data[1][i]) / (polygon_Data[1][j] - polygon_Data[1][i]) * (polygon_Data[0][j] - polygon_Data[0][i]) < point_X)
            {
                cross_Total++;
            }
        }
    }
    return cross_Total & 0b1;
}
forward Float:GetDist3D(Float:x, Float:y, Float:z, Float:x2, Float:y2, Float:z2);
stock Float:GetDist3D(Float:x, Float:y, Float:z, Float:x2, Float:y2, Float:z2)
	return floatsqroot((x-x2)*(x-x2)+(y-y2)*(y-y2)+(z-z2)*(z-z2));

forward Float:GetDist2D(Float:x, Float:y, Float:x2, Float:y2);
stock Float:GetDist2D(Float:x, Float:y, Float:x2, Float:y2)
	return floatsqroot((x-x2)*(x-x2)+(y-y2)*(y-y2));

stock IsPlayerBehindPlayer(playerid, targetid, Float:dOffset)
{
	new
	    Float:pa,
	    Float:ta;
	if(!IsPlayerConnected(playerid) || !IsPlayerConnected(targetid)) return 0;
	GetPlayerFacingAngle(playerid, pa);
	GetPlayerFacingAngle(targetid, ta);
	if(AngleInRangeOfAngle(pa, ta, dOffset) && IsPlayerFacingPlayer(playerid, targetid, dOffset)) return true;
	return false;
}
stock SetPlayerToFacePlayer(playerid, targetid)
{
	new
		Float:pX,
		Float:pY,
		Float:pZ,
		Float:X,
		Float:Y,
		Float:Z,
		Float:ang;
	if(!IsPlayerConnected(playerid) || !IsPlayerConnected(targetid)) return 0;
	GetPlayerPos(targetid, X, Y, Z);
	GetPlayerPos(playerid, pX, pY, pZ);
	if( Y > pY ) ang = (-acos((X - pX) / floatsqroot((X - pX)*(X - pX) + (Y - pY)*(Y - pY))) - 90.0);
	else if( Y < pY && X < pX ) ang = (acos((X - pX) / floatsqroot((X - pX)*(X - pX) + (Y - pY)*(Y - pY))) - 450.0);
	else if( Y < pY ) ang = (acos((X - pX) / floatsqroot((X - pX)*(X - pX) + (Y - pY)*(Y - pY))) - 90.0);
	if(X > pX) ang = (floatabs(floatabs(ang) + 180.0));
	else ang = (floatabs(ang) - 180.0);
	SetPlayerFacingAngle(playerid, ang);
 	return 0;
}
stock IsPlayerFacingPlayer(playerid, targetid, Float:dOffset)
{
	new
		Float:pX,
		Float:pY,
		Float:pZ,
		Float:pA,
		Float:X,
		Float:Y,
		Float:Z,
		Float:ang;
	if(!IsPlayerConnected(playerid) || !IsPlayerConnected(targetid)) return 0;
	GetPlayerPos(targetid, pX, pY, pZ);
	GetPlayerPos(playerid, X, Y, Z);
	GetPlayerFacingAngle(playerid, pA);
	if( Y > pY ) ang = (-acos((X - pX) / floatsqroot((X - pX)*(X - pX) + (Y - pY)*(Y - pY))) - 90.0);
	else if( Y < pY && X < pX ) ang = (acos((X - pX) / floatsqroot((X - pX)*(X - pX) + (Y - pY)*(Y - pY))) - 450.0);
	else if( Y < pY ) ang = (acos((X - pX) / floatsqroot((X - pX)*(X - pX) + (Y - pY)*(Y - pY))) - 90.0);
	if(AngleInRangeOfAngle(-ang, pA, dOffset)) return true;
	return false;
}
stock AngleInRangeOfAngle(Float:a1, Float:a2, Float:range)
{

	a1 -= a2;
	if((a1 < range) && (a1 > -range)) return true;

	return false;

}
stock GetLandingPoint(Float: fX, Float: fY, Float: fZ, Float: fSlope, Float: fAngle, Float: fVelo, &Float: fEndX, &Float: fEndY, &Float: fEndZ, &Float: fTime = 0.0, &Float: fLength = 0.0)
{
    static const
		Float: fGravity = 9.81;

	new
		Float: fVX = floatcos(fSlope, degrees),
		Float: fVY = floatsin(fSlope, degrees);

	fTime = (2.0 * fVY * fVelo) / fGravity;
	fLength = fVX * fVelo * fTime;

	fEndX = fX + fLength * floatsin(-fAngle, degrees);
	fEndY = fY + fLength * floatcos(-fAngle, degrees);

	fEndZ = fZ;
}

//==============================================================================Server Functions

FormatColours(string[])
{
	new tmpString[256];
	format(tmpString, 256, string);
	for(new x;x<sizeof(cArray);x++)
	{
	    new
			iLoop,
			iFind,
			cnLen = strlen(cArray[x][colour_name]),
			ctLen = strlen(cArray[x][colour_text]),
			stLen = strlen(tmpString);

	    while(iLoop < stLen)
	    {
	    	iFind=strfind(tmpString, cArray[x][colour_name], true, iLoop);
	    	if(iFind!=-1)
			{
			    if( (tmpString[iFind-1]=='{') && (tmpString[iFind+cnLen]=='}') )
			    {
				    strdel(tmpString, iFind, iFind+cnLen);
					strins(tmpString, cArray[x][colour_text], iFind, ctLen);
					iLoop=iFind+ctLen;
				}
				else break;
			}
			else break;
		}
	}
	return tmpString;
}
stock BoolToString(input, type=0, capital=1)
{
	new tmpStr[9];
	if(input>0)
	{
		if(type==0)tmpStr="true";
		if(type==1)tmpStr="yes";
		if(type==2)tmpStr="on";
		if(type==3)tmpStr="in";
		if(type==4)tmpStr="positive";
	}
	else
	{
		if(type==0)tmpStr="false";
		if(type==1)tmpStr="no";
		if(type==2)tmpStr="off";
		if(type==3)tmpStr="out";
		if(type==4)tmpStr="negative";
	}

	if(capital)toupper(tmpStr[0]);
	return tmpStr;
}
stock StringToBool(string[])
{
	new
	TrueBools[]=
	{"true",	"yes",	"on",	"in",	"positive"},
	FalseBools[]=
	{"false",	"no",	"off",	"out",	"negetive"},
	bool:result;
	for(new i;i<sizeof(TrueBools);i++)
	{
		if(!strcmp(string,TrueBools[i],true))
		{result=true;break;}
		if(!strcmp(string,FalseBools[i],true))
		{result=false;break;}
	}
	return result;
}
stock IsNumeric(const string[])
{
	for(new i,j=strlen(string);i<j;i++)if (string[i] > '9' || string[i] < '0') return 0;
	return 1;
}
stock UnderscoreToSpace(name[])
{
	new pos = strfind(name,"_", true);
	if( pos != -1 )name[pos] = ' ';
}

stock IsKeyJustDown(key, newkeys, oldkeys)
{
	if((newkeys & key) && !(oldkeys & key)) return 1;
	return 0;
}
stock IsDateReached(day,month,year)
{
	new myday,mymonth,myyear;
	getdate(myyear,mymonth,myday);
	if(myday   >=	day) 	return 1;
	if(mymonth >	month) 	return 1;
	if(myyear  >	year) 	return 1;
	return 0;
}


